/******************************************************************************
 * This program is a 100% Java Email Server.
 ******************************************************************************
 * Copyright (c) 2001-2011, Eric Daugherty (http://www.ericdaugherty.com)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************
 * For current versions and more information, please visit:
 * http://javaemailserver.sf.net/
 *
 * or contact the authors at:
 * java@ericdaugherty.com
 * andreaskyrmegalos@hotmail.com
 *
 ******************************************************************************
 * This program is based on the CSRMail project written by Calvin Smith.
 * http://crsemail.sourceforge.net/
 ******************************************************************************
 *
 * $Rev$
 * $Date$
 *
 ******************************************************************************/

package com.ericdaugherty.mail.server.info;

//Log imports
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;

//Local imports
import com.ericdaugherty.mail.server.configuration.PasswordFactory;
import com.ericdaugherty.mail.server.persistence.POP3MessagePersistenceFactory;
import com.ericdaugherty.mail.server.persistence.POP3MessagePersistenceProccessor;

/**
 * Represents a user object.  This class is responsible for providing all
 * information about a specific user and their mailbox.
 * 
 * @author Eric Daugherty
 */
public class User {

    //***************************************************************
    // Variables
    //***************************************************************

    private String username;
    private String domain;
    private String password;
    private EmailAddress[] forwardAddresses;

    private Message[] messages = null;

    private final POP3MessagePersistenceProccessor pOP3MessagePersistenceProccessor;

    /** Logger */
    private Log log = LogFactory.getLog( User.class );

    //***************************************************************
    // Constructor
    //***************************************************************

    /**
     * Creates a new user with the full username (user and domain).
     * The username and domain fields are not allowed to have their
     * values changed for the entire life-cycle of an instance of this
     * class.
     *
     * @param address User's full email address
     */
    public User( EmailAddress address )
    {

        username = address.getUsername();
        domain = address.getDomain();

        if (!(address.isNULL()||address.isMailerDaemon())) {
           pOP3MessagePersistenceProccessor = POP3MessagePersistenceFactory.getInstance().getPOP3PersistenceProccessor();
        }
        else {
           pOP3MessagePersistenceProccessor = POP3MessagePersistenceFactory.getInstance().getNullPeristenceProccessor();
        }
        pOP3MessagePersistenceProccessor.setUser(this);
    }

    //***************************************************************
    // Public Interface
    //***************************************************************

    /**
     * Returns true if and only if the specified plain text password's hash
     * value matches the hashed password for this user.
     *
     * @param plainTextPassword the password to validate.
     * @return true if it matches.
     */
    public boolean isPasswordValid( String plainTextPassword )
    {
        if( log.isDebugEnabled() ) log.debug( "Authenticating User: " + getFullUsername() );
        boolean result = PasswordFactory.getInstance().getPasswordHasher().passwordMatches(getPassword(), plainTextPassword);
        if( log.isDebugEnabled() && !result ) log.debug( "Authentication Failed for User: " + getFullUsername() );

        return result;
    }

    //***************************************************************
    //JavaBean Methods
    
    public String getUsername(){ return username; }

    public String getDomain(){ return domain; }

    public String getFullUsername() { return getFullUsername( username, domain ); }

    public EmailAddress getEmailAddress() { return EmailAddress.getEmailAddress(username, domain); }

    public String getPassword(){ return password; }

    public void setPassword(String password){ this.password = password; }

    public EmailAddress[] getForwardAddresses(){ return forwardAddresses; }

    public void setForwardAddresses(EmailAddress[] forwardAddresses){ this.forwardAddresses = forwardAddresses; }

    /**
     * Returns an array of Strings that represent email addresses to deliver
     * email to this user.  If the forwardAddresses is not null or empty,
     * this will return the forwardAddresses array.  Otherwise, this will return
     * the user's email address.
     *
     * @return array of strings that represent email addresses.
     */
    public EmailAddress[] getDeliveryAddresses() {

        if( forwardAddresses != null && forwardAddresses.length > 0 ) {
            return forwardAddresses;
        }
        else {
            return new EmailAddress[] { EmailAddress.getEmailAddress( getUsername(),  getDomain() ) };
        }
    }

    /**
     * Returns an array of Message objects that represents all messages
     * stored for this user.
     */
    public Message[] getMessages() {
        
        if( messages == null ) {
            
            String[] fileNames = pOP3MessagePersistenceProccessor.populatePOP3MessageList();
            
            int numMessage = fileNames.length;
            
            messages = new Message[numMessage];
            Message currentMessage;
            
            for( int index = 0; index < numMessage; index++ ) {
                currentMessage = new Message();
                currentMessage.setMessageLocation( fileNames[index] );
                messages[index ] = currentMessage;
            }
        }
        return messages;
    }
    
    /**
     * Returns an array of Message objects that represents all messaged
     * stored for this user not marked for deletion.
     */
    public Message[] getNonDeletedMessages() {
       Message[] allMessages = getMessages();
       int allCount = allMessages.length;
       int nonDeletedCount = 0;
       for (int i=0;i<allCount;i++) {
          if (!allMessages[i].isDeleted()) {
             nonDeletedCount++;
          }
       }
       Message[] nonDeletedMessages = new Message[nonDeletedCount];
       nonDeletedCount = 0;
       for (int i=0;i<allCount;i++) {
          if (!allMessages[i].isDeleted()) {
             nonDeletedMessages[nonDeletedCount++] = allMessages[i];
          }
       }
       return nonDeletedMessages;
    }
    
    /**
     * Gets the specified message.  Message numbers are 1 based.  
     * This method counts on the calling method to verify that the
     * messageNumber actually exists.
     */
    public Message getMessage( int messageNumber ) {
        
        return getMessages()[messageNumber - 1];
    }
         
    /**
     * Gets the total number of messages currently stored for this user.
     */
    public long getNumberOfMessage() {
        
        return getMessages().length;
    }
         
    /**
     * Gets the total number of non deleted messages currently stored for this user.
     */
    public long getNumberOfNonDeletedMessages() {
        
        return getNonDeletedMessages().length;
    }
    
    /**
     * Gets the total size of the non deleted messages currently stored for this user.
     */
    public long getSizeOfAllNonDeletedMessages() {
        
        Message[] message = getNonDeletedMessages();
        
        long totalSize = 0;
        
        for ( int index = 0; index < message.length; index++) {
            totalSize += message[index].getMessageSize(this);
        }
        
        return totalSize;
    }
    
    /**
     * This method removes any cached message information this user may have stored
     */
    public void reset() {

        messages = null;
    }
    
    //***************************************************************
    // Private Interface
    //***************************************************************
        
    /**
     * Converts a username and domain to the combined string representation of an e-mail address.
     */
    private String getFullUsername( String username, String domain ) {

        return username + '@' + domain;
    }

   public POP3MessagePersistenceProccessor getPOP3MessagePersistenceProccessor() {
      return pOP3MessagePersistenceProccessor;
   }

}
